#ifndef __ZOMBIEMANAGER_H__
#define __ZOMBIEMANAGER_H__

#include <Ogre.h>
#include <btBulletDynamicsCommon.h>
#include <list>
#include "BtOgrePG.h"
#include "BtOgreGP.h"
#include "BtOgreExtras.h"
#include "ZombieSwarm.h"
#include "ZombieSpawner.h"
#include "Human.h"

class ZombieManager : public Ogre::Singleton<ZombieManager> {

 private:

  // Atributos Bullet --------------------------------------------------

  btDiscreteDynamicsWorld* _pWorld;
  btCylinderShape* _pZombieCollisionShape;
  btCylinderShape* _pBossCollisionShape;

  // Atributos Ogre ----------------------------------------------------

  Ogre::SceneManager* _pSceneManager;

  // Otros atributos ---------------------------------------------------

  Human* _pHuman; // Sabroso humano (personaje jugador)

  std::list<ZombieSwarm*> _swarms; // Hordas
  std::list<ZombieSwarm*>::iterator _swarmsIt;

  std::list<Zombie*> _zombies; // Zombis
  std::list<Zombie*>::iterator _zombiesIt;

  std::list<ZombieSpawner*> _spawners; // Generadores
  std::list<ZombieSpawner*>::iterator _spawnersIt;

 public:

  // Constructores y destructores --------------------------------------

  ZombieManager(btDiscreteDynamicsWorld* pWorld,
                Ogre::SceneManager* pSceneManager,
                Human* pHuman);
  ~ZombieManager();

  // Ogre::Singleton ---------------------------------------------------

  static ZombieManager& getSingleton();
  static ZombieManager* getSingletonPtr();

  // Factory -----------------------------------------------------------

  // Crea una horda de n zombis en una posición dada
  ZombieSwarm* createSwarm(OpenSteer::Vec3 position, int nZombies);

  // Crea un zombi en una posición dada
  Zombie* createZombie(OpenSteer::Vec3 position,
                       ZombieSwarm* pSwarm = NULL);

  // Crea un generador de zombis en una posición dada
  ZombieSpawner* createSpawner(OpenSteer::Vec3 position,
                               int spawnTime, int maxZombies = 0);

  // Crea al jefe zombi en una posición dada
  Zombie* createBoss(OpenSteer::Vec3 position);

  // Update ------------------------------------------------------------

  // Llamar al metodo update en todos los zombis
  void update(const float currentTime, const float elapsedTime);
  void updateSwarms(const float currentTime, const float elapsedTime);
  void updateZombies(const float currentTime, const float elapsedTime);
  void updateSpawners(const float currentTime, const float elapsedTime);

  // Delete ------------------------------------------------------------

  void deleteZombie(Zombie* pZombie);
  void deleteSwarm(ZombieSwarm* pZombieSwarm);
  //void deleteSpawner(ZombieSpawner* pZombieSpawner);
};

#endif
